package com.cljz.makepassenger.base;

import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.Application;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.sqlite.SQLiteDatabase;
import android.support.multidex.MultiDex;

import com.baidu.mapapi.SDKInitializer;
import com.cljz.makepassenger.service.LocationService;
import com.cljz.makepassenger.utils.FileUtils;
import com.cljz.makepassenger.utils.L;
import com.clzj.makepassenger.dao.DaoMaster;
import com.clzj.makepassenger.dao.DaoSession;
import com.hyphenate.chat.EMClient;
import com.hyphenate.chat.EMOptions;
import com.hyphenate.easeui.controller.EaseUI;
import com.tencent.smtt.sdk.QbSdk;
import com.tencent.smtt.sdk.TbsListener;
import com.umeng.socialize.PlatformConfig;
import com.umeng.socialize.UMShareAPI;
import com.umeng.socialize.UMShareConfig;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import cn.droidlover.xdroidmvp._1QConfig;
import cn.droidlover.xdroidmvp.net.NetError;
import cn.droidlover.xdroidmvp.net.NetProvider;
import cn.droidlover.xdroidmvp.net.RequestHandler;
import cn.droidlover.xdroidmvp.net.XApi;
import cn.jpush.android.api.JPushInterface;
import okhttp3.CookieJar;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;

/**
 * Created by apple on 2017/3/31.
 */

public class App extends Application {
    /**
     * 是否是调试模式，统一使用该全局的debug变量
     */
    public static final boolean DEBUG = _1QConfig.DEV;

    /**
     * 用来保存当前该Application的context
     */
    public static Context instance;
    /**
     * 用来保存最新打开页面的context
     */
    private volatile static WeakReference<Context> instanceRef = null;

    /**
     * 用来存放一些在软件启动生命周期之内需要存放的变量和数据，但存放的数据量不宜过大，
     * 如果需要存放过大的数据，请在使用完之后，立马清除，还有一点需要注意的是该maps可
     * 能会因为应用在后台，手机内存不足而被回收，回收之后该maps会被清空!!
     */
    public static HashMap<String, Object> appMaps;
    private static LocationService locationService;


    public DaoSession daoSession;

    public SQLiteDatabase db;

    public DaoMaster.DevOpenHelper helper;

    public DaoMaster daoMaster;


    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        appMaps = new HashMap<>();

        initTbs();
        initTripartiteSDK();
        initXApi();
        initEM();
        initGreenDao();
    }

    private void initTbs() {
        //搜集本地tbs内核信息并上报服务器，服务器返回结果决定使用哪个内核。
        QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() {

            @Override
            public void onViewInitFinished(boolean arg0) {
                L.e("onViewInitFinished is " + arg0);
            }

            @Override
            public void onCoreInitFinished() {
            }
        };

        QbSdk.setTbsListener(new TbsListener() {
            @Override
            public void onDownloadFinish(int i) {
                L.e("onDownloadFinish");
            }

            @Override
            public void onInstallFinish(int i) {
                L.e("onInstallFinish");
            }

            @Override
            public void onDownloadProgress(int i) {
                L.e("onDownloadProgress:" + i);
            }
        });

        QbSdk.initX5Environment(getApplicationContext(), cb);
    }

    private void initEM() {
        EMOptions options = new EMOptions();
        // 默认添加好友时，是不需要验证的，改成需要验证
        options.setAcceptInvitationAlways(false);
        int pid = android.os.Process.myPid();
        String processAppName = getAppName(pid);
        // 如果APP启用了远程的service，此application:onCreate会被调用2次
        // 为了防止环信SDK被初始化2次，加此判断会保证SDK被初始化1次
        // 默认的APP会在以包名为默认的process name下运行，如果查到的process name不是APP的process name就立即返回
        if (processAppName == null || !processAppName.equalsIgnoreCase(this.getPackageName())) {
            // 则此application::onCreate 是被service 调用的，直接返回
            return;
        }
        //初始化
        EMClient.getInstance().init(this, options);
        EaseUI.getInstance().init(this, options);
        //在做打包混淆时，关闭debug模式，避免消耗不必要的资源
        EMClient.getInstance().setDebugMode(false);

    }

    private String getAppName(int pID) {
        String processName = null;
        ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
        List l = am.getRunningAppProcesses();
        Iterator i = l.iterator();
        PackageManager pm = this.getPackageManager();
        while (i.hasNext()) {
            ActivityManager.RunningAppProcessInfo info = (ActivityManager.RunningAppProcessInfo) (i.next());
            try {
                if (info.pid == pID) {
                    processName = info.processName;
                    return processName;
                }
            } catch (Exception e) {
                // Log.d("Process", "Error>> :"+ e.toString());
            }
        }
        return processName;
    }

    private void initGreenDao() {
        helper = new DaoMaster.DevOpenHelper(this, Constant.DB_NAME, null);
        db = helper.getWritableDatabase();
        daoMaster = new DaoMaster(db);
        daoSession = daoMaster.newSession();
    }

    public static LocationService getLocationService() {
        if (locationService == null) {
            locationService = new LocationService(instance);
        }
        return locationService;
    }


    private void initTripartiteSDK() {
        JPushInterface.setDebugMode(false);    // 设置开启日志,发布时关闭日志
        JPushInterface.init(this);            // 初始化 JPush

        SDKInitializer.initialize(getApplicationContext());

        PlatformConfig.setWeixin("wx5ccb4e3fb7104a47", "1beeb3e7c35e4a6ecee1f38357eba405");
        PlatformConfig.setSinaWeibo("274790880", "7c7598ea8eef46f5c2deb3956dd3a0a4", "http://sns.whalecloud.com");
        PlatformConfig.setQQZone("1105664359", "V4J9XJjUlbx3PJfW");

        UMShareAPI.get(this);
        UMShareConfig config = new UMShareConfig();
        config.isNeedAuthOnGetUserInfo(true);
        UMShareAPI.get(this).setShareConfig(config);

    }

    private void initXApi() {
        XApi.registerProvider(new NetProvider() {

            @Override
            public Interceptor[] configInterceptors() {
                return new Interceptor[0];
            }

            @Override
            public void configHttps(OkHttpClient.Builder builder) {

            }

            @Override
            public CookieJar configCookie() {
                return null;
            }

            @Override
            public RequestHandler configHandler() {
                return null;
            }

            @Override
            public long configConnectTimeoutMills() {
                return 0;
            }

            @Override
            public long configReadTimeoutMills() {
                return 0;
            }

            @Override
            public boolean configLogEnable() {
                return true;
            }

            @Override
            public boolean handleError(NetError error) {
                return false;
            }
        });
    }

    /**
     * 该函数用来返回一个context，一般情况下为当前activity的context，如果为空，
     * 就会调用{@linkplain com.cljz.makepassenger.utils.ActivityManager#getActivity()}方法去获取栈顶context,
     * 但是如果activity没有调用 {@link #setInstanceRef(Context)}方法去设置context,
     * 就会使用整个Application的context，相当于{@link #getApplicationContext()},
     * 不推荐使用该方法，特别是耗时任务，因为会导致页面销毁时，任务无法回收，导致内存泄露和
     * 其他异常
     *
     * @return context上下文，如果返回Null检测manifest文件是否设置了application的name
     */
    public static Context getInstance() {
        if (instanceRef == null || instanceRef.get() == null) {
            synchronized (App.class) {
                if (instanceRef == null || instanceRef.get() == null) {
                    Context context = com.cljz.makepassenger.utils.ActivityManager.getInstance().getActivity();
                    if (context != null)
                        instanceRef = new WeakReference<>(context);
                    else {
                        instanceRef = new WeakReference<>(instance);
                    }
                }
            }
        }
        return instanceRef.get();
    }

    /**
     * 将{@link #instanceRef}设置为最新页面的context
     *
     * @param context 最新页面的context
     */
    public static void setInstanceRef(Context context) {
        instanceRef = new WeakReference<>(context);
    }

    /**
     * 检测应用是否退出，并且在应用退出的时候做相关的处理
     */
    public static void checkApplicationDestroy() {
        //应用被关闭，删除需要删除的相关目录和文件
        if (com.cljz.makepassenger.utils.ActivityManager.getInstance().getActivity() == null) {
            FileUtils.clearExternalStorageTemp();
        }
    }

    /**
     * 处理崩溃异常，并且在崩溃异常之后重启<br/>
     * <strong>Android对待所有传递给Context.startActivity()的 隐式intent好像它们至少包含
     * "android.intent.category.DEFAULT"（对应CATEGORY_DEFAULT常量）。
     * 因此，活动想要接收隐式intent必须要在intent过滤器中包含"android.intent.category.DEFAULT"</strong>
     */
    private class MyExceptionHandler implements Thread.UncaughtExceptionHandler {

        @Override
        public void uncaughtException(Thread thread, Throwable ex) {
            //启动首页
            Intent intent = new Intent();
            intent.setAction("android.intent.action.MAIN");
            intent.addCategory("android.intent.category.LAUNCHER");
            intent.addCategory("com.android.framework.MAINPAGE");
            PendingIntent restartIntent = PendingIntent.getActivity(getInstance(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
            //退出程序
            AlarmManager mgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
            mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent);
            com.cljz.makepassenger.utils.ActivityManager.getInstance().finishAllActivityWithoutClose();
        }
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }

    public DaoSession getDaoSession() {
        return daoSession;
    }

}
